package us.icitap.commandcenter.business.ejb;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Vector;
import java.util.logging.Level;

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.ejb.Stateful;
import javax.ejb.Stateless;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;

import us.icitap.commandcenter.CommandCenterUI;
import us.icitap.commandcenter.business.AppUser;
import us.icitap.commandcenter.business.Result;
import us.icitap.commandcenter.business.ejb.dao.Expression;
import us.icitap.commandcenter.business.ejb.dao.Operator;
import us.icitap.commandcenter.business.ejb.dao.QueryBuilder;
import us.icitap.commandcenter.business.ejb.persistence.AppLog;
import us.icitap.commandcenter.business.ejb.persistence.Call;
import us.icitap.commandcenter.business.ejb.persistence.CallReason;
import us.icitap.commandcenter.business.ejb.persistence.CallStatusEnum;
import us.icitap.commandcenter.business.ejb.persistence.CallStatusHistory;
import us.icitap.commandcenter.business.ejb.persistence.CommandCenter;
import us.icitap.commandcenter.business.ejb.persistence.Dispatcher;
import us.icitap.commandcenter.business.ejb.persistence.UniqueNumber;
import us.icitap.commandcenter.ui.dispatcher.CallMessage;
import us.icitap.commandcenter.utils.HandleNotification;
import us.icitap.commandcenter.utils.Utils;


@Stateless
public class AppStatelessBean implements IAppStatelessBean {

	@Resource(name = "jms/TestConnectionFactory")
	public  ConnectionFactory connectionFactory;
	
	@EJB
	IPersistenceBean persistenceBean;
	
	@Override
	public Result<AppUser> login(){

		AppUser user = new AppUser();

		user.setUsername("USER_TEST");
		user.setLoginDate(new Date());
		
		Result<CommandCenter> result = persistenceBean.findEntityById(139, CommandCenter.class);
		if(result.isSucceeded()){
			user.setCommandCenter(result.getObject());
			return new Result<AppUser>(user, true, null);
		}
		else
			return new Result<AppUser>(null, false, result.getMessage());
	}
	

	@Override
	public void sendMessage(Call call, CallStatusEnum prevoiusStatus,boolean sendToDispatcher){ 
		MessageProducer messageProducer;
		MessageProducer msgProdSupervisor;
	  
	    try {
	    	
	    	Connection connection = connectionFactory.createConnection();
	        Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
	        
	        Destination destSupervisor = session.createTopic("SUPERVISOR" + call.getCommandCenter().getId());
	        msgProdSupervisor = session.createProducer(destSupervisor);
	        
	        CallMessage callMessage = new CallMessage(call, prevoiusStatus);
	       
	        ObjectMessage objectMessage = session.createObjectMessage();
	        objectMessage.setObject(callMessage);
	        
	        msgProdSupervisor.send(objectMessage);
	        msgProdSupervisor.close();
	        
	        
	        if(sendToDispatcher){
	        	Destination dest = session.createTopic("DISP" + call.getMainDispatcher().getId().toString());
	 	        messageProducer = session.createProducer(dest);
	 	        messageProducer.send(objectMessage);       
		        messageProducer.close();
	        }
	       

	        session.close();
	        connection.close();
	        
	      
		} catch (Exception e) {
			e.printStackTrace();
			System.err.println(e.getMessage());
		}
	}
	

	
	
	@Override
	public Result<List<Call>> getOperatorCallList(String username){
		List<Expression> exp = new ArrayList<Expression>();
		
		Date[] shiftLimits = Utils.ShiftLimits();
		exp.add(new Expression("recordUser", username, Operator.EQ));
		exp.add(new Expression("recordDate", shiftLimits[0], Operator.GREATER_EQ_THAN));
		exp.add(new Expression("recordDate", shiftLimits[1], Operator.LOWER_THAN ));
		
		Result<List<Call>> result = persistenceBean.findByCriteria(exp, null, null, Call.class);
		
		return result;
	}
	
	@Override
	public Result<List<Call>> getInitialNewCallList(List<Dispatcher> dispatchers) {
		List<Expression> expNewCall = new ArrayList<Expression>();

		if(dispatchers.size() > 1)
			expNewCall.add(new Expression("mainDispatcher", dispatchers, Operator.EQ));	
		else
			expNewCall.add(new Expression("mainDispatcher", dispatchers.get(0), Operator.EQ));
		
		//exp.add(new Expression("recordDate", c.getTime(), Operator.GREATER_EQ_THAN));
		expNewCall.add(new Expression("actualStatus", CallStatusEnum.N, Operator.EQ));

		Result<List<Call>> result = persistenceBean.findByCriteria(expNewCall, null, null, Call.class);
		
		return result;
	}
	
	
	@Override
	public Result<List<Call>> getWvCallList(List<Dispatcher> dispatchers) {
		List<Expression> expWvCall = new ArrayList<Expression>();
		if(dispatchers.size() > 1)
			expWvCall.add(new Expression("mainDispatcher", dispatchers, Operator.EQ));
		else
			expWvCall.add(new Expression("mainDispatcher", dispatchers.get(0), Operator.EQ));
		
		expWvCall.add(new Expression("actualStatus", CallStatusEnum.WV, Operator.EQ));
		
		Result<List<Call>> result = persistenceBean.findByCriteria(expWvCall, null, null, Call.class);
		
		return result;
		
	}
	
	@Override
	public Result<List<Call>> getClosedCallList(List<Dispatcher> dispatchers) {
		List<Expression> expCloseCall = new ArrayList<Expression>();
		
		
		if(dispatchers.size() > 1){
			
			expCloseCall.add(new Expression("mainDispatcher", dispatchers, Operator.EQ));
		}
			
		else{
			
			expCloseCall.add(new Expression("mainDispatcher", dispatchers, Operator.EQ));
		}
			
		expCloseCall.add(new Expression("actualStatus", CallStatusEnum.V, Operator.EQ));
		Date[] shiftLimits = Utils.ShiftLimits();
		
		expCloseCall.add(new Expression("verificationDate", shiftLimits[0], Operator.GREATER_EQ_THAN));
		expCloseCall.add(new Expression("verificationDate", shiftLimits[1], Operator.LOWER_THAN));
		Result<List<Call>> result = persistenceBean.findByCriteria(expCloseCall, null, null, Call.class);
		return result;
	}
	
	
	
	
	@Override
	public Result<Call> startVerification(Call call){
		Result<Call> result = persistenceBean.saveEntity(call);
		if(result.isSucceeded()){
			this.sendMessage(call, CallStatusEnum.N, false);	
		}
		return result;
	
	}
	
	@Override
	public Result<Call> updateCallInformation(Call call){
		Result<Call> result = persistenceBean.saveEntity(call);
		if(result.isSucceeded()){
			this.sendMessage(call, CallStatusEnum.WV, false);	
		}
		return result;	
	}
	
	@Override
	public Result<Call> closeVerification(Call call){
		Result<Call> result = persistenceBean.saveEntity(call);
		if(result.isSucceeded()){
			this.sendMessage(call, CallStatusEnum.WV, false);
			
		}
		return result;
	}
	
	@Override
	public Result<Call> generateUniqueNumber(Call call){
		Result<Call> result = CommandCenterUI.persistenceBean.generateUniqueNumber(call);
		if(result.isSucceeded()){
			this.sendMessage(call, CallStatusEnum.V, false);
			
		}
		return result;
	}
	
	@Override
	public Result<Call> addNewCall(Call call, boolean sendToDispatcher){
		Result<Call> result = persistenceBean.createCall(call);
		if(result.isSucceeded()){
			this.sendMessage(result.getObject(), null, sendToDispatcher);
		}
		return result;	
	}
	
	@Override
	public ConnectionFactory getConnectionFactory(){
		return connectionFactory;
	}
	
}

